﻿namespace com.oakwoodsys.ConsultantCare
{
    using System;
    using System.Collections.Generic;

    using com.oakwoodsys.ConsultantCareDao;
    using com.oakwoodsys.Extensions.DoubleExtensions;

    using Microsoft.SharePoint;

    public class CalendarEventCreator
    {
        #region Fields

        const int ACTIVITYSCHEDULEDMINUTES = 15;
        const int MAXYEARS = 2;

        #endregion Fields

        #region Constructors

        public CalendarEventCreator( )
        {
        }

        #endregion Constructors

        #region Methods

        public void AddCalendarEvents( string webUrl, Consultant consultant, List<ConsultantCareActivity> activities )
        {
            List<CalendarEvent> calendarEvents = CreateCalendarEvents( consultant, activities );

            foreach ( CalendarEvent calendarEvent in calendarEvents )
            {
                Guid calendarEventID = addCalendarEvent( webUrl, calendarEvent );

                addRelationship( webUrl, consultant.UniqueId, calendarEvent.ActivityID, calendarEventID );
            }
        }

        Guid addCalendarEvent( string webUrl, CalendarEvent calendarEvent )
        {
            CalendarEventDao dao = new CalendarEventDao( webUrl );
            return dao.Add( calendarEvent );
        }

        void addRelationship( string webUrl, Guid consultantID, Guid activityID, Guid calendarEventID )
        {
            ConsultantActivityID value = new ConsultantActivityID
            {
                ActivityID = activityID.ToString( ),
                CalendarEventID = calendarEventID.ToString( ),
                ConsultantID = consultantID.ToString( )
            };
            ConsultantActivityIDDao dao = new ConsultantActivityIDDao( webUrl );
            dao.Add( value );
        }

        List<CalendarEvent> CreateCalendarEvents( Consultant consultant, List<ConsultantCareActivity> activities )
        {
            List<CalendarEvent> calendarEvents = new List<CalendarEvent>( );
            foreach ( ConsultantCareActivity activity in activities )
            {
                DateTime d = consultant.StartDate.Value;
                DateTime startDate = new DateTime( d.Year, d.Month, d.Day, 8, 0, 0 );

                if ( activity.Recurring.HasValue && activity.Recurring.Value )
                {
                    calendarEvents.AddRange( createRecurringEvents( startDate, activity, consultant ) );
                }
                else
                {
                    DateTime eventDate = startDate.AddDays( activity.NDays.Value );
                    DateTime endDate = eventDate.AddMinutes( ACTIVITYSCHEDULEDMINUTES );
                    calendarEvents.Add( createEvent( eventDate, endDate, activity, consultant ) );
                }
            }
            return calendarEvents;
        }

        CalendarEvent createEvent( DateTime eventDate, DateTime endDate, ConsultantCareActivity activity, Consultant consultant )
        {
            return new CalendarEvent
               {
                   ActivityID = activity.UniqueId,
                   AllDayEvent = false,
                   Category = "Consultant Care",
                   Description = activity.Message,
                   EndDate = endDate,
                   StartTime = eventDate,
                   Title = string.Format( "{0} :: {1}", consultant.Title, activity.Title )
               };
        }

        List<CalendarEvent> createEvery2MonthEvents( DateTime startDate, ConsultantCareActivity activity, Consultant consultant )
        {
            List<CalendarEvent> calendarEvents = new List<CalendarEvent>( );
            // explode for MAXYEARS
            for ( int i = 1; i <= MAXYEARS * 6; i++ )
            {
                DateTime eventDate = startDate.AddMonths( i * 2 );
                DateTime endDate = eventDate.AddMinutes( ACTIVITYSCHEDULEDMINUTES );
                calendarEvents.Add( createEvent( eventDate, endDate, activity, consultant ) );
            }
            return calendarEvents;
        }

        List<CalendarEvent> createEvery6MonthEvents( DateTime startDate, ConsultantCareActivity activity, Consultant consultant )
        {
            List<CalendarEvent> calendarEvents = new List<CalendarEvent>( );
            // explode for MAXYEARS
            for ( int i = 1; i <= MAXYEARS * 2; i++ )
            {
                DateTime eventDate = startDate.AddMonths( i * 6 );
                DateTime endDate = eventDate.AddMinutes( ACTIVITYSCHEDULEDMINUTES );
                calendarEvents.Add( createEvent( eventDate, endDate, activity, consultant ) );
            }
            return calendarEvents;
        }

        List<CalendarEvent> createMonthlyEvents( DateTime startDate, ConsultantCareActivity activity, Consultant consultant )
        {
            List<CalendarEvent> calendarEvents = new List<CalendarEvent>( );
            // explode for MAXYEARS
            for ( int i = 1; i <= MAXYEARS * 12; i++ )
            {
                DateTime eventDate = startDate.AddMonths( i * 1 );
                DateTime endDate = eventDate.AddMinutes( ACTIVITYSCHEDULEDMINUTES );
                calendarEvents.Add( createEvent( eventDate, endDate, activity, consultant ) );
            }
            return calendarEvents;
        }

        List<CalendarEvent> createQuarterlyEvents( DateTime startDate, ConsultantCareActivity activity, Consultant consultant )
        {
            List<CalendarEvent> calendarEvents = new List<CalendarEvent>( );
            // explode for MAXYEARS
            for ( int i = 1; i <= MAXYEARS * 4; i++ )
            {
                DateTime eventDate = startDate.AddMonths( i * 3 );
                DateTime endDate = eventDate.AddMinutes( ACTIVITYSCHEDULEDMINUTES );
                calendarEvents.Add( createEvent( eventDate, endDate, activity, consultant ) );
            }
            return calendarEvents;
        }

        List<CalendarEvent> createRecurringEvents( DateTime startDate, ConsultantCareActivity activity, Consultant consultant )
        {
            List<CalendarEvent> calendarEvents = new List<CalendarEvent>( );

            if ( activity.IsYearlyOccurrence )
                calendarEvents.AddRange( createYearlyEvents( startDate, activity, consultant ) );
            else if ( activity.IsEvery6MonthOccurrence )
                calendarEvents.AddRange( createEvery6MonthEvents( startDate, activity, consultant ) );
            else if ( activity.IsQuarterlyOccurrence )
                calendarEvents.AddRange( createQuarterlyEvents( startDate, activity, consultant ) );
            else if ( activity.IsEvery2MonthOccurrence )
                calendarEvents.AddRange( createEvery2MonthEvents( startDate, activity, consultant ) );
            else if ( activity.IsMonthlyOccurrence )
                calendarEvents.AddRange( createMonthlyEvents( startDate, activity, consultant ) );
            else
            {
                // explode for MAXYEARS
                int n = activity.NDays.Value.ToInt32( );
                DateTime maxDate = startDate.AddYears( MAXYEARS );
                bool ok = true;
                int i = 0;
                while ( ok )
                {
                    i++;
                    DateTime eventDate = startDate.AddDays( i * n );
                    DateTime endDate = eventDate.AddMinutes( ACTIVITYSCHEDULEDMINUTES );
                    if ( eventDate > maxDate )
                    {
                        ok = false;
                        break;
                    }
                    calendarEvents.Add( createEvent( eventDate, endDate, activity, consultant ) );
                }
            }
            return calendarEvents;
        }

        List<CalendarEvent> createYearlyEvents( DateTime startDate, ConsultantCareActivity activity, Consultant consultant )
        {
            List<CalendarEvent> calendarEvents = new List<CalendarEvent>( );
            // explode for MAXYEARS
            for ( int i = 1; i <= MAXYEARS; i++ )
            {
                DateTime eventDate = startDate.AddYears( i );
                DateTime endDate = eventDate.AddMinutes( ACTIVITYSCHEDULEDMINUTES );
                calendarEvents.Add( createEvent( eventDate, endDate, activity, consultant ) );
            }
            return calendarEvents;
        }

        #endregion Methods
    }
}